package com.zoe.onelink.core.web.jackson.sensitive.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StringSerializer;
import com.zoe.onelink.annotation.web.jackson.sentitive.SensitiveParam;
import com.zoe.onelink.common.enumeration.ExceptionCodeEnum;
import com.zoe.onelink.common.exception.ApiException;
import com.zoe.onelink.core.web.jackson.sensitive.strategy.ISensitiveStrategy;
import com.zoe.onelink.core.web.jackson.sensitive.strategy.SensitiveStrategyManager;
import lombok.Setter;

import java.io.IOException;
import java.util.Optional;

/**
 * <p>标题: 脱敏序列化器</p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-11-10
 */
@Setter
public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private Class<?> clazz;
    private ISensitiveStrategy sensitiveStrategy;
    private String[] args;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (this.sensitiveStrategy == null) {
            throw ApiException.createEx(ExceptionCodeEnum.SERIALIZATION_SENSITIVE_NO_SUCH_STRATEGY, gen.getOutputContext().getCurrentName());

        }
        String writeVal = this.sensitiveStrategy.handle(this.clazz, value, this.args);
        gen.writeString(writeVal);
    }


    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        // 获取字段注解
        SensitiveParam sensitiveParam = Optional.ofNullable(property.getAnnotation(SensitiveParam.class))
                .orElse(property.getContextAnnotation(SensitiveParam.class));
        if (sensitiveParam == null) {
            return new StringSerializer();
        }
        // 脱敏策略
        ISensitiveStrategy sensitiveStrategy = SensitiveStrategyManager.get(sensitiveParam.value());
        // 创建脱敏序列化实例
        SensitiveSerializer sensitiveSerializer = new SensitiveSerializer();
        sensitiveSerializer.setClazz(property.getType().getRawClass());
        sensitiveSerializer.setSensitiveStrategy(sensitiveStrategy);
        sensitiveSerializer.setArgs(sensitiveParam.args());
        return sensitiveSerializer;
    }

}
